package com.sc.nft.admin.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sc.nft.admin.request.AddEquityPropsRequest;
import com.sc.nft.admin.request.EditEquityPropsRequest;
import com.sc.nft.admin.request.EditEquityPropsShowFlagRequest;
import com.sc.nft.admin.request.EditEquityPropsStatusRequest;
import com.sc.nft.admin.request.EquityDataRequest;
import com.sc.nft.admin.request.EquityPropsExpiredLogPageRequest;
import com.sc.nft.admin.request.EquityPropsGetLogPageRequest;
import com.sc.nft.admin.request.EquityPropsUseLogPageRequest;
import com.sc.nft.admin.request.GetUserEquityPropsPageRequest;
import com.sc.nft.admin.request.IdAndOrderNoRequest;
import com.sc.nft.admin.request.IdRequest;
import com.sc.nft.admin.request.PageAdminEquityPropsRequest;
import com.sc.nft.admin.request.ProdctAssociateEquityPropsRequest;
import com.sc.nft.admin.request.UserEquityPropsBatchEditExpiredTimeRequest;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.config.hna.HnaConfig;
import com.sc.nft.dao.HfTransDao;
import com.sc.nft.dao.MallPayOrderRecordDao;
import com.sc.nft.dao.PayOrderDao;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.dto.HnaRefundDto;
import com.sc.nft.dto.llian.LlRandomPwdDTO;
import com.sc.nft.entity.HfTrans;
import com.sc.nft.entity.MallPayOrderRecord;
import com.sc.nft.entity.PayOrder;
import com.sc.nft.entity.SysMember;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.dto.MerchantAvailabilityListDTO;
import com.sc.nft.entity.vo.AdminUserEquityPropsPagVO;
import com.sc.nft.entity.vo.EquityPropsDetailVO;
import com.sc.nft.entity.vo.EquityPropsExpiredLogPageVO;
import com.sc.nft.entity.vo.EquityPropsGetLogPageVO;
import com.sc.nft.entity.vo.EquityPropsUseLogPageVO;
import com.sc.nft.entity.vo.MerchantAvailabilityListVO;
import com.sc.nft.entity.vo.PageAdminEquityPropsVO;
import com.sc.nft.entity.vo.ProdctAssociateEquityPropsVO;
import com.sc.nft.enums.PayStatusEnum;
import com.sc.nft.enums.UserEquityPropsGetTypeEnum;
import com.sc.nft.enums.UserEquityPropsUseTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.HfPayHelper;
import com.sc.nft.helper.LlPayHelper;
import com.sc.nft.pool.SysMemberPool;
import com.sc.nft.service.EquityPropsService;
import com.sc.nft.service.UserEquityPropsService;
import com.sc.nft.service.UserHnaExtService;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import com.sc.nft.util.OrderNoUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/equity")
@Api(tags = "后台权益道具")
public class AdminEquityPropsController {

    private final EquityPropsService equityPropsService;
    private final HfTransDao hfTransDao;
    private final UserHnaExtService userHnaExtService;
    private final HnaConfig hnaConfig;
    private final UserEquityPropsService userEquityPropsService;
    private final MallPayOrderRecordDao mallPayOrderRecordDao;

    @PostMapping(value = "/getPageAdminEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取权益道具列表", notes = "获取权益道具列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<PageAdminEquityPropsVO> getPageAdminEquityProps(@Valid @RequestBody PageAdminEquityPropsRequest request) {
        return PageResult.success(equityPropsService.getPageAdminEquityProps(request.getFirstTitle(), request.getStatus(), request.getShowFlag(), request.getPageNo(), request.getPageSize()));
    }

    @PostMapping(value = "/addEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "添加权益道具", notes = "添加权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result addEquityProps(@Valid @RequestBody AddEquityPropsRequest request) {
        equityPropsService.addEquityProps(request.getFirstTitle(), request.getGetRulesUrl(), request.getCreationContent(), request.getProductDetails(), request.getIsExpired(), request.getExpiredDay(), request.getIsBrandUse(), request.getTypeClassify(), request.getIsGift(), request.getAging(), request.getAddEquityPropsGiftDTO(), request.getVistIn(), request.getDaoId());
        return Result.success();
    }

    @PostMapping(value = "/editEquityPropsStatus", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "编辑权益道具上/下架", notes = "编辑权益道具上/下架", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editEquityPropsStatus(@Valid @RequestBody EditEquityPropsStatusRequest request) {
        equityPropsService.editEquityPropsStatus(request.getId(), request.getStatus());
        return Result.success();
    }


    @PostMapping(value = "/editEquityPropsShowFlag", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "编辑权益道具是否展示", notes = "编辑权益道具是否展示", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editEquityPropsShowFlag(@Valid @RequestBody EditEquityPropsShowFlagRequest request) {
        equityPropsService.editEquityPropsShowFlag(request.getId(), request.getShowFlag());
        return Result.success();
    }

    @PostMapping(value = "/editEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "编辑权益道具", notes = "编辑权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editEquityProps(@Valid @RequestBody EditEquityPropsRequest request) {
        equityPropsService.editEquityProps(request.getId(), request.getGetRulesUrl(), request.getFirstTitle(), request.getCreationContent(), request.getProductDetails(), request.getIsExpired(), request.getExpiredDay(), request.getIsBrandUse(), request.getTypeClassify(), request.getIsGift(), request.getAging(), request.getAddEquityPropsGiftDTO(), request.getVistIn(), request.getDaoId());
        return Result.success();
    }

    @PostMapping(value = "/deleteEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "删除权益道具", notes = "删除权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editEquityProps(@Valid @RequestBody IdRequest request) {
        equityPropsService.deleteEquityProps(request.getId());
        return Result.success();
    }

    @PostMapping(value = "/getProdctAssociateEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "(新建/修改商品/cdk活动)关联权益道具", notes = "产品关联权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<ProdctAssociateEquityPropsVO> prodctAssociateEquityProps(@Valid @RequestBody ProdctAssociateEquityPropsRequest request) {
        return PageResult.success(equityPropsService.prodctAssociateEquityProps(request.getPageNo(), request.getPageSize(), request.getFirstTitle()));
    }

    private final PayOrderDao payOrderDao;
    private final UserInfoDao userInfoDao;
    private final LlPayHelper llPayHelper;
    private final HfPayHelper hfPayHelper;

    @ApiOperation(value = "临时退款()", notes = "临时退款", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/llRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<LlRandomPwdDTO> llRefund(@RequestBody @Valid IdAndOrderNoRequest request) {
        SysMember member = SysMemberPool.getMember();
        if (!member.getId().equals(18L) && !member.getId().equals(26L) && !member.getId().equals(66L)) {
            throw new GlobalRunTimeException("无权限");
        }
        PayOrder byId = payOrderDao.getById(request.getId());
        switch (byId.getChannel()) {
            case HF_PAY:
                hfPayHelper.refund(byId.getUserId(),
                        StrUtil.isNotBlank(request.getOriOrderNo()) ? request.getOriOrderNo() :
                                byId.getTradeNo(), UUID.randomUUID().toString(true), byId.getPayTime(), byId.getPayAmount(), null, null);
                break;
            case LL_PAY:
                llPayHelper.refund(userInfoDao.getById(byId.getUserId()), byId.getTradeNo(), OrderNoUtil.getOrderNo(), byId.getPayAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString(), "",byId);
                break;
            case HNA_PAY:
                HnaRefundDto dto = new HnaRefundDto();
                dto.setOrderAmount(byId.getPayAmount().toString());
                dto.setRefundAmount(dto.getOrderAmount());
                dto.setRefundType("1");
                dto.setRemark("手动退款");
                dto.setOrgSubmitTime(DateUtil.format(byId.getCreateTime(),
                        DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
                dto.setOrgMerOrderId(byId.getTradeNo());
                dto.setNotifyUrl(hnaConfig.getT005NonMallNotifyUrl());
                UserInfo userInfo = new UserInfo();
                userInfo.setId(byId.getUserId());
                userHnaExtService.refund(userInfo, dto);
                break;
        }
        byId.setStatus(PayStatusEnum.INIT);
        byId.updateById();
        return Result.success();
    }

    @ApiOperation(value = "商城临时退款", notes = "商城临时退款", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/mall/llRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<LlRandomPwdDTO> mallLlRefund(@RequestBody @Valid IdAndOrderNoRequest request) {
        SysMember member = SysMemberPool.getMember();
        if (!member.getId().equals(18L) && !member.getId().equals(26L) && !member.getId().equals(66L)) {
            throw new GlobalRunTimeException("无权限");
        }
        MallPayOrderRecord mallPayOrderRecord = mallPayOrderRecordDao.getById(request.getId());
        switch (mallPayOrderRecord.getChannel()) {
            case HF_PAY:
                hfPayHelper.refund(mallPayOrderRecord.getUserId(),
                        StrUtil.isNotBlank(request.getOriOrderNo()) ? request.getOriOrderNo() :
                                mallPayOrderRecord.getTradeNo(), UUID.randomUUID().toString(true), mallPayOrderRecord.getPayTime(),
                        mallPayOrderRecord.getPayAmount(), null, null);
                break;
            case LL_PAY:
                llPayHelper.refundMall(userInfoDao.getById(mallPayOrderRecord.getUserId()), mallPayOrderRecord.getTradeNo(), OrderNoUtil.getOrderNo(), mallPayOrderRecord.getPayAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString(), "");
                break;
            case HNA_PAY:
                HnaRefundDto dto = new HnaRefundDto();
                dto.setOrderAmount(mallPayOrderRecord.getPayAmount().toString());
                dto.setRefundAmount(dto.getOrderAmount());
                dto.setRefundType("1");
                dto.setRemark("手动退款");
                dto.setOrgSubmitTime(DateUtil.format(mallPayOrderRecord.getCreateTime(),
                        DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
                dto.setOrgMerOrderId(mallPayOrderRecord.getTradeNo());
                dto.setNotifyUrl(hnaConfig.getT005NonMallNotifyUrl());
                UserInfo userInfo = new UserInfo();
                userInfo.setId(mallPayOrderRecord.getUserId());
                userHnaExtService.refund(userInfo, dto);
                break;
        }
        mallPayOrderRecord.setStatus(PayStatusEnum.INIT);
        mallPayOrderRecord.updateById();
        return Result.success();
    }

    @ApiOperation(value = "临时退货", notes = "临时退货", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/hfRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<LlRandomPwdDTO> hfRefund(@RequestBody @Valid IdAndOrderNoRequest request) {
        PayOrder byId = payOrderDao.getById(request.getId());
        switch (byId.getChannel()) {
            case HF_PAY:
                hfPayHelper.refund2(byId.getUserId(), byId.getPayTime(),
                        StrUtil.isNotBlank(request.getOriOrderNo()) ? request.getOriOrderNo() :
                                byId.getTradeNo(), UUID.randomUUID().toString(true), byId.getPayTime(), byId.getPayAmount(), null, null);

        }
        byId.setStatus(PayStatusEnum.INIT);
        byId.updateById();
        return Result.success();
    }

    @ApiOperation(value = "汇付把钱分给平台", notes = "汇付把钱分给平台", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/hfSplit", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<LlRandomPwdDTO> hfSplit(@RequestBody @Valid IdAndOrderNoRequest request) {
        PayOrder byId = payOrderDao.getById(request.getId());
        hfPayHelper.subLedger(byId.getTradeNo(), DateUtil.format(byId.getPayTime(), "yyyyMMdd"), byId.getPayAmount().setScale(2).toPlainString(), request.getOriOrderNo());
        HfTrans byPayOrderId = hfTransDao.getByPayOrderId(byId.getId());
        if (ObjectUtil.isNotNull(byPayOrderId)) {
            byPayOrderId.deleteById();
        }

        return Result.success();
    }

    @PostMapping(value = "/simpleAvailabilityList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "虚拟道具可用列表", notes = "虚拟道具可用列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<MerchantAvailabilityListVO> simpleAvailabilityList(@RequestBody MerchantAvailabilityListDTO merchantAvailabilityListDTO) {
        return PageResult.success(equityPropsService.simpleAvailabilityList(merchantAvailabilityListDTO), MerchantAvailabilityListVO.class);
    }


    @PostMapping(value = "/equityPropAllPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "虚拟道具所有可用列表", notes = "虚拟道具所有可用列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<MerchantAvailabilityListVO> equityPropAllPage(@RequestBody PageRequest pageRequest) {
        return PageResult.success(equityPropsService.equityPropAllPage(pageRequest.toMp()), MerchantAvailabilityListVO.class);
    }


    @PostMapping(value = "/getLongTermEquityPropPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取长期有效的权益道具列表", notes = "获取长期有效的权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<MerchantAvailabilityListVO> getLongTermEquityPropPage(@RequestBody MerchantAvailabilityListDTO request) {
        return PageResult.success(equityPropsService.getLongTermEquityPropPage(request.getFirstTitle(), request.getType(), request.toMp()), MerchantAvailabilityListVO.class);
    }

    @PostMapping(value = "/getDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "道具卡总览", notes = "道具卡总览", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<EquityPropsDetailVO> getDetail(@Valid @RequestBody EquityDataRequest request) {
        return Result.success(equityPropsService.getDetail(request.getFirstTitle()));
    }

    @PostMapping(value = "/getType", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取来源类型", notes = "获取来源类型", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<Map<String, String>>> getType() {
        List result = Lists.newArrayList();
        for (UserEquityPropsGetTypeEnum value : UserEquityPropsGetTypeEnum.values()) {
            Map<String, String> map = new HashMap<>();
            map.put("value", value.toString());
            map.put("code", String.valueOf(value.getCode()));
            map.put("description", value.getDescription());
            result.add(map);
        }
        return Result.success(result);
    }

    @PostMapping(value = "/useType", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "使用来源类型", notes = "使用来源类型", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<Map<String, String>>> useType() {
        List result = Lists.newArrayList();
        for (UserEquityPropsUseTypeEnum value : UserEquityPropsUseTypeEnum.values()) {
            Map<String, String> map = new HashMap<>();
            map.put("value", value.toString());
            map.put("code", String.valueOf(value.getCode()));
            map.put("description", value.getDescription());
            result.add(map);
        }
        return Result.success(result);
    }

    @PostMapping(value = "/getLog", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取记录", notes = "获取记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<EquityPropsGetLogPageVO> getLog(@RequestBody EquityPropsGetLogPageRequest request) {
        if (ObjectUtil.isNull(request.getStartTime()) ^ ObjectUtil.isNull(request.getEndTime())) {
            return PageResult.fail("开始时间和结束时间需要一起选");
        }
        return PageResult.success(equityPropsService.getLog(request.getPropId(), request.getUserTel(),
                request.getFirstTitle(), request.getGetType(),
                request.getStartTime(), request.getEndTime(),
                request.getPageNo(), request.getPageSize()));
    }

    @PostMapping(value = "/useLog", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "使用记录", notes = "使用记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<EquityPropsUseLogPageVO> useLog(@RequestBody EquityPropsUseLogPageRequest request) {
        if (ObjectUtil.isNull(request.getStartTime()) ^ ObjectUtil.isNull(request.getEndTime())) {
            return PageResult.fail("开始时间和结束时间需要一起选");
        }
        return PageResult.success(equityPropsService.useLog(request.getUserTel(),
                request.getFirstTitle(), request.getUseType(),
                request.getStartTime(), request.getEndTime(),
                request.getPageNo(), request.getPageSize()));
    }

    @PostMapping(value = "/expiredLog", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "失效记录", notes = "失效记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<EquityPropsExpiredLogPageVO> expiredLog(@RequestBody EquityPropsExpiredLogPageRequest request) {
        if (ObjectUtil.isNull(request.getStartTime()) ^ ObjectUtil.isNull(request.getEndTime())) {
            return PageResult.fail("开始时间和结束时间需要一起选");
        }
        return PageResult.success(equityPropsService.expiredLog(request.getUserTel(), request.getFirstTitle(),
                request.getStartTime(), request.getEndTime(),
                request.getPageNo(), request.getPageSize()));
    }


    @PostMapping(value = "/getUserEquityPropsPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户的权益道具列表", notes = "获取用户的权益道具列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<AdminUserEquityPropsPagVO> getAdminUserEquityPropsPage(@Valid @RequestBody GetUserEquityPropsPageRequest request) {
        return PageResult.success(userEquityPropsService.getAdminUserEquityPropsPage(request.getUserTel(), request.getFirstTitle(), request.getGetBeginTime(), request.getGetEndTime(), request.getExpiredBeginTime(), request.getExpiredEndTime(), request.toMp(), request.getOnConsignStatus()));
    }


    @PostMapping(value = "/batchEditExpiredTime", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "批量修改用户权益道具的过期时间", notes = "批量修改用户权益道具的过期时间", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result batchEditExpiredTime(@Valid @RequestBody UserEquityPropsBatchEditExpiredTimeRequest request) {
        userEquityPropsService.batchEditExpiredTime(request.getIds(), request.getExpiredTime());
        return Result.success();
    }
}
